package com.baipiao.permission.backend.config.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
//开启权限注解
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfig {

    //白名单
    @Autowired
    SecurityConfigProperties securityConfigProperties;

    //登录认证处理
    @Autowired
    CustomUserDetailsService CustomUserDetailsService;

    //登录成功处理逻辑
    @Autowired
    CustomAuthenticationSuccessHandler authenticationSuccessHandler;

    //登录失败处理逻辑
    @Autowired
    CustomAuthenticationFailureHandler authenticationFailureHandler;

    //权限拒绝处理逻辑
    @Autowired
    CustomizeAccessDeniedHandler accessDeniedHandler;

    //匿名用户访问无权限资源时的异常
    @Autowired
    CustomAuthenticationEntryPoint authenticationEntryPoint;

    //会话失效(账号被挤下线)处理逻辑
    @Autowired
    CustomSessionInformationExpiredStrategy sessionInformationExpiredStrategy;

    //登出成功处理逻辑
    @Autowired
    CustomLogoutSuccessHandler logoutSuccessHandler;

    // 设置默认的加密方式（强hash方式加密）
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                //csrf
                .csrf(AbstractHttpConfigurer::disable)//前后端分离项目，关闭csrf
                //登录认证处理
                .userDetailsService(CustomUserDetailsService)
                .formLogin(item -> item
                        .permitAll()//允许所有用户
                        .successHandler(authenticationSuccessHandler)// 登录成功处理逻辑
                        .failureHandler(authenticationFailureHandler)// 登录失败处理逻辑
                )
                //退出
                .logout(item -> item
                        .permitAll()//允许所有用户
                        .logoutSuccessHandler(logoutSuccessHandler)// 登出成功处理逻辑
                        .deleteCookies()//退出后删除cookie
                )
                //授权管理
                .authorizeHttpRequests(item -> item
                        .requestMatchers(securityConfigProperties.getWhitelist().toArray(new String[0])).permitAll()//配置放行资源
                        .anyRequest().authenticated()//除了以上资源，都需要认证通过后才能访问
                )
                // 会话管理
                .sessionManagement(item -> item
                        .maximumSessions(1)//同一账号同时登录最大用户数
                        .expiredSessionStrategy(sessionInformationExpiredStrategy)// 会话失效(账号被挤下线)处理逻辑，401
                )
                // 异常处理(权限拒绝、登录失效等)
                .exceptionHandling(item -> item
                        .accessDeniedHandler(accessDeniedHandler)// 权限拒绝处理逻辑，403
                        .authenticationEntryPoint(authenticationEntryPoint)// 匿名用户访问无权限资源时的异常处理，401
                );
        //使配置生效
        return http.build();
    }

}
